#!/usr/bin/env bash
# This should create a dashboard and a PAAC URL at the end on http
#
# You should forward the URL via smee,
# - create a URL in there by going to https://hook.pipelinesascode.com
# - install gosmee: go install -v github.com/chmouel/gosmee@latest
# - run somewhere in a terminal :
#    gosmee client https://hook.pipelinesascode.com/aBcDeF http://controller.paac-127-0-0-1.nip.io
#
# You probably need to install passwordstore https://www.passwordstore.org/ and
# add your github secrets : github-application-id github-private-key
# webhook.secret in a folder which needs to be specified  in
# the PAC_PASS_SECRET_FOLDER variable. or otherwise you have to create the
# pipelines-as-code-secret manually
#
# If you need to install old pac as shipped in OSP1.7, you check it out somewhere
# and set the PAC_DIR to it. It will automatically set the ingress to the right
# place.
set -euf
cd $(dirname $(readlink -f ${0}))

export KIND_CLUSTER_NAME=${KIND_CLUSTER_NAME:-kind}
export KUBECONFIG=${HOME}/.kube/config.${KIND_CLUSTER_NAME}
export TARGET=kubernetes
export DOMAIN_NAME=paac-127-0-0-1.nip.io

if [ -z "${TEST_GITEA_SMEEURL}" ]; then
  echo "You should forward the URL via smee, create a URL in there by going to https://hook.pipelinesascode.com"
  echo "set it up as environement variable in the 'TEST_GITEA_SMEEURL=https://hook.pipelinesascode.com/XXXXXXXX' variable"
  exit 1
fi
if ! builtin type -p kind &>/dev/null; then
  echo "Install kind. https://kind.sigs.k8s.io/docs/user/quick-start/#installation"
  exit 1
fi
kind=$(type -p kind)
if ! builtin type -p ko &>/dev/null; then
  echo "Install ko. https://ko.build/install/"
  exit 1
fi
ko=$(type -p ko)
if ! builtin type -p gosmee &>/dev/null; then
  echo "Install gosmee. https://github.com/chmouel/gosmee?tab=readme-ov-file#install"
  exit 1
fi

TMPD=$(mktemp -d /tmp/.GITXXXX)
REG_PORT='5000'
REG_NAME='kind-registry'
INSTALL_FROM_RELEASE=
PAC_PASS_SECRET_FOLDER=${PAC_PASS_SECRET_FOLDER:-""}
SUDO=sudo
PAC_DIR=${PAC_DIR:-""}
DISABLE_GITEA=${DISABLE_GITEA:-""}
GITEA_HOST=${GITEA_HOST:-"localhost:3000"}
NO_REINSTALL_KIND=${NO_REINSTALL_KIND:-""}

[[ $(uname -s) == "Darwin" ]] && {
  SUDO=
}

# cleanup on exit (useful for running locally)
cleanup() { rm -rf ${TMPD}; }
trap cleanup EXIT

function start_registry() {
  running="$(docker inspect -f '{{.State.Running}}' ${REG_NAME} 2>/dev/null || echo false)"

  if [[ ${running} != "true" ]]; then
    docker rm -f kind-registry || true
    docker run \
      -d --restart=always -p "127.0.0.1:${REG_PORT}:5000" \
      -e REGISTRY_HTTP_SECRET=secret \
      --name "${REG_NAME}" \
      registry:2
  fi
}

function reinstall_kind() {
  ${SUDO} $kind delete cluster --name ${KIND_CLUSTER_NAME} || true
  sed "s,%DOCKERCFG%,${HOME}/.docker/config.json," kind.yaml >${TMPD}/kconfig.yaml

  cat <<EOF >>${TMPD}/kconfig.yaml
containerdConfigPatches:
- |-
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${REG_PORT}"]
    endpoint = ["http://${REG_NAME}:5000"]
EOF

  ${SUDO} ${kind} create cluster --name ${KIND_CLUSTER_NAME} --config ${TMPD}/kconfig.yaml
  mkdir -p $(dirname ${KUBECONFIG})
  ${SUDO} ${kind} --name ${KIND_CLUSTER_NAME} get kubeconfig >${KUBECONFIG}

  docker network connect "kind" "${REG_NAME}" 2>/dev/null || true
  cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: local-registry-hosting
  namespace: kube-public
data:
  localRegistryHosting.v1: |
    host: "localhost:${REG_PORT}"
    help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF

}

function install_nginx() {
  echo "Installing nginx"
  kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml >/dev/null
  i=0
  echo -n "Waiting for nginx to come up: "
  while true; do
    [[ ${i} == 120 ]] && exit 1
    ep=$(kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=180s 2>/dev/null || true)
    [[ -n ${ep} ]] && break
    sleep 5
    i=$((i + 1))
  done
  echo "done."
}

function install_tekton() {
  echo "Installing Tekton Pipeline"
  kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml >/dev/null
  echo "Installing Tekton Dashboard"
  kubectl apply --filename https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml >/dev/null
  i=0
  echo -n "Waiting for tekton pipeline to come up: "
  for tt in webhook controller; do
    while true; do
      [[ ${i} == 120 ]] && exit 1
      ep=$(kubectl get ep -n tekton-pipelines tekton-pipelines-$tt -o jsonpath='{.subsets[*].addresses[*].ip}')
      [[ -n ${ep} ]] && break
      sleep 2
      i=$((i + 1))
    done
  done
  echo "done."

  maxloop=5
  loop=0
  while true; do
    [[ ${loop} == "${maxloop}" ]] && exit 1
    echo "Enable step actions feature flag"
    kubectl patch configmap -n tekton-pipelines --type merge -p '{"data":{"enable-step-actions": "true"}}' feature-flags && break
    sleep 2
    loop=$((loop + 1))
  done
  echo "Installing Dashboard Ingress"
  sed -e "s,%DOMAIN_NAME%,${DOMAIN_NAME}," ingress-dashboard.yaml | kubectl apply -f-
}

function install_pac() {
  [[ -z ${PAC_DIR} && $(git rev-parse --show-toplevel 2>/dev/null) != "" ]] &&
    PAC_DIR=$(git rev-parse --show-toplevel)

  [[ -z ${PAC_DIR} && $(git rev-parse --show-toplevel 2>/dev/null) == "" ]] &&
    PAC_DIR=$GOPATH/src/github.com/openshift-pipelines/pipelines-as-code

  if [[ -n ${INSTALL_FROM_RELEASE} ]]; then
    kubectl apply -f ${PAC_RELEASE:-https://github.com/openshift-pipelines/pipelines-as-code/raw/stable/release.k8s.yaml}
  else
    [[ -d ${PAC_DIR} ]] || {
      echo "I cannot find the PAC installation directory, set the variable \$PAC_DIR to define it. or launch this script from inside where the pac code is checkout"
      exit 1
    }
    oldPwd=${PWD}
    cd ${PAC_DIR}
    echo "Deploying PAC from ${PAC_DIR}"
    if [[ -n ${PAC_DEPLOY_SCRIPT:-""} ]]; then
      ${PAC_DEPLOY_SCRIPT}
    else
      env KO_DOCKER_REPO=localhost:5000 $ko apply -f config --sbom=none -B >/dev/null
    fi
    cd ${oldPwd}
  fi
  configure_pac
  echo "controller: http://controller.${DOMAIN_NAME}"
  echo "dashboard: http://dashboard.${DOMAIN_NAME}"
}

function configure_pac() {
  kubectl get service -n pipelines-as-code
  service_name=pipelines-as-code-controller
  kubectl get service -n pipelines-as-code -o name |
    sed 's/.*\///' |
    grep -q el-pipelines-as-code-interceptor &&
    service_name=el-pipelines-as-code-interceptor

  sed -e "s,%DOMAIN_NAME%,${DOMAIN_NAME}," -e "s,%SERVICE_NAME%,${service_name}," ingress-pac.yaml | kubectl apply -f-

  kubectl patch configmap -n pipelines-as-code -p "{\"data\":{\"bitbucket-cloud-check-source-ip\": \"false\"}}" pipelines-as-code &&
    kubectl patch configmap -n pipelines-as-code -p "{\"data\":{\"tekton-dashboard-url\": \"http://dashboard.${DOMAIN_NAME}\"}}" --type merge pipelines-as-code
  # add custom catalog so we can use it in e2e, this will points to the normal upstream hub so we can easily use it
  kubectl patch configmap -n pipelines-as-code -p '{"data":{"catalog-1-id": "custom", "catalog-1-name": "tekton", "catalog-1-url": "https://api.hub.tekton.dev/v1"}}' --type merge pipelines-as-code
  # add one more custom catalog so we can use it in e2e for multiple catalog support, this will points to the normal upstream hub so we can easily use it
  kubectl patch configmap -n pipelines-as-code -p '{"data":{"catalog-2-id": "custom2", "catalog-2-name": "tekton", "catalog-2-url": "https://api.hub.tekton.dev/v1"}}' --type merge pipelines-as-code
  set +x
  if [[ -n ${PAC_PASS_SECRET_FOLDER} ]]; then
    echo "Installing PAC secrets"
    kubectl delete secret pipelines-as-code-secret -n pipelines-as-code 2>/dev/null || true
    kubectl create secret generic pipelines-as-code-secret -n pipelines-as-code
    for passk in github-application-id github-private-key webhook.secret; do
      if [[ ${passk} == *-key ]]; then
        b64d=$(pass show ${PAC_PASS_SECRET_FOLDER}/${passk} | base64 -w0)
      else
        b64d=$(echo -n $(pass show ${PAC_PASS_SECRET_FOLDER}/${passk}) | base64 -w0)
      fi
      kubectl patch secret -n pipelines-as-code -p "{\"data\":{\"${passk}\": \"${b64d}\"}}" \
        --type merge pipelines-as-code-secret >/dev/null
    done
  else
    echo "No secret has been installed"
    echo "you need to create a pass https://www.passwordstore.org/ folder with"
    echo "github-application-id github-private-key webhook.secret information in there"
    echo "and export the PAC_PASS_SECRET_FOLDER variable to that folder"
    echo "or install your pipelines-as-code-secret manually"
    kubectl delete secret -n pipelines-as-code pipelines-as-code-secret >/dev/null 2>/dev/null || true
  fi

  echo "Set Active Namespace to pipelines-as-code"
  kubectl config set-context --current --namespace=pipelines-as-code >/dev/null
  echo "Run: gosmee client --saveDir /tmp/replays ${TEST_GITEA_SMEEURL} http://controller.${DOMAIN_NAME}"
}

function install_gitea() {
  env GITEA_URL="http://${GITEA_HOST}" GITEA_HOST=$GITEA_HOST GITEA_USER="pac" \
    GITEA_PASSWORD="pac" GITEA_REPO_NAME="pac-e2e" ./gitea/deploy.py
}

main() {
  if [[ -z ${NO_REINSTALL_KIND} ]]; then
    start_registry
    reinstall_kind
  else
    echo "Skipping kind reinstall"
  fi
  install_nginx
  install_tekton
  install_pac
  [[ -z ${DISABLE_GITEA} ]] && install_gitea
  echo "And we are done :): "
}

function usage() {
  cat <<EOF
Usage: $0 [OPTIONS]

Options:
  -h          Show this message
  -b          Only install the registry/kind/nginx and tekton and don't install PAC
  -c          Configure PAC
  -p          Install only PAC
  -g          Install only Gitea
  -G          Disable Gitea when installing
  -r          Install from release instead of local checkout with ko
  -R          Restart the PAC pods
  -O          Don't reinstall kind or registry and continue the whole install of tekton/dashboard/nginx/pac
EOF
}

while getopts "ROGhgpcrb" o; do
  case "${o}" in
  h)
    usage
    exit
    ;;
  b)
    start_registry
    reinstall_kind
    install_nginx
    install_tekton
    exit
    ;;
  c)
    configure_pac
    exit
    ;;
  p)
    install_pac
    exit
    ;;
  R)

    echo "Restarting pac pods"
    kubectl delete pod -l app.kubernetes.io/part-of=pipelines-as-code -n pipelines-as-code || true
    ;;
  r)
    INSTALL_FROM_RELEASE=yes
    ;;
  O)
    NO_REINSTALL_KIND=yes
    ;;
  g)
    install_gitea
    exit
    ;;
  G)
    DISABLE_GITEA=yes
    ;;

  *)
    echo "Invalid option"
    exit 1
    ;;
  esac
done
shift $((OPTIND - 1))

main
